/*
* OpLab.cpp
*
*  Created on: Apr 2, 2010
*      Author: Sequoyha
*/

#include "OpLab.h"

//CONSTRUCTORS - DEFAULT, NUMER ONLY, INPUT
Fraction::Fraction():numerator(0), denominator(1){Normalize();}
Fraction::Fraction(int num):numerator(num), denominator(1){Normalize();}
Fraction::Fraction(int num, int den):numerator(num), denominator(den){Normalize();}

//SETTERS
void Fraction::setNumerator(int num){numerator = num;}
void Fraction::setDenominator(int den){denominator = den;}

//GETTERS
int Fraction::GetNumer(){return numerator;}
int Fraction::GetDenom(){return denominator;}

//OVERLOADED METHEMATICAL OPERATORS
Fraction Fraction::operator +(const Fraction& obj)
{
	int objNumerator; //Temporary int for Calculations
	Fraction result; //Target object

	//Multiplying terms to get Common terms
	result.setNumerator(this->numerator * obj.denominator);
	objNumerator = obj.numerator * this->denominator;
	result.setDenominator(this->denominator * obj.denominator);
	//Adding numerators together
	result.numerator +=objNumerator;
	//Reducing to LCV
	result.Normalize();
	return result;
}

Fraction Fraction::operator -(const Fraction& obj)
{
	int objNumerator;	//Temporary int for Calculations
	Fraction result;	//Target object

	//Multiplying terms to get Common terms
	result.setNumerator(this->numerator * obj.denominator);
	objNumerator = obj.numerator * this->denominator;
	result.setDenominator(this->denominator * obj.denominator);
	//Subtracting numerators for result
	result.numerator -=objNumerator;
	//Reducing to LCV
	result.Normalize();
	return result;
}
Fraction Fraction::operator *(const Fraction& obj)
{
	Fraction result;	//Target object
	//Multiply for result
	result.setNumerator(this->numerator * obj.numerator);
	result.setDenominator(this->denominator * obj.denominator);
	//Reducing to LCV
	result.Normalize();
	return result;
}
Fraction Fraction::operator /(const Fraction& obj)
{
	Fraction result;	//Target object
	//Flipping 2nd fraction for division of fractions
	Fraction reverseObj(obj.denominator, obj.numerator);
	//Call Multiply operator to get result
	result = this->operator *(reverseObj);
	//Reducing to LCV
	result.Normalize();
	return result;
}
//Copy constructor
Fraction Fraction::operator =(const Fraction& obj)
{
	this->setNumerator(obj.numerator);
	this->setDenominator(obj.denominator);

	return *this;
}
//REALATIONAL OPERATORS
bool Fraction::operator<(const Fraction& obj)
{
	//CallCompare obj to get value and run through
	//parameters to get boolean result
	if(Compare(obj) < 0 )
		return true;
	else
		return false;
}

bool Fraction::operator<=(const Fraction& obj)
{
	//CallCompare obj to get value and run through
	//parameters to get boolean result
	if(Compare(obj) < 0 || Compare(obj) == 0)
		return true;
	else
		return false;
}

bool Fraction::operator>(const Fraction& obj)
{
	//CallCompare obj to get value and run through
	//parameters to get boolean result
	if(Compare(obj) > 0)
		return true;
	else
		return false;
}

bool Fraction::operator>=(const Fraction& obj)
{
	//CallCompare obj to get value and run through
	//parameters to get boolean result
	if(Compare(obj) > 0 || Compare(obj) == 0)
		return true;
	else
		return false;
}

bool Fraction::operator==(const Fraction& obj)
{
	//CallCompare obj to get value and run through
	//parameters to get boolean result
	if(Compare(obj) == 0)
		return true;
	else
		return false;
}

bool Fraction::operator!=(const Fraction& obj)
{
	//CallCompare obj to get value and run through
	//parameters to get boolean result
	if(Compare(obj) != 0)
		return true;
	else
		return false;
}

//NORMALIZE FUNCTION AS DESCRIBED PER ASSIGNMENT REQUIREMENTS
void Fraction::Normalize()
{
	int sign, div;
	sign = div = 1;

	if(numerator < 0)
	{
		numerator *= -1;
		sign *= -1;
	}
	if(denominator < 0)
	{
		denominator *= -1;
		sign *=-1;
	}
	if(numerator > 0)
	{
		div = Gcd(numerator, denominator);
	}
	numerator = sign * (numerator/div);
	denominator = denominator/div;
}

//FINDS GREATEST COMMON DENOMINATOR
int Fraction::Gcd(int numer, int denom)
{
	//DO YOU MIND IF I CODE SMALL IF/ELSE STATEMENTS LIKE THIS?
	//IT SAVES ROOM AND IS STILL EASY TO READ (LOOKS NICE TO ME)
	if(denom == 0){return numer;}
	else{return Gcd(denom, numer % denom);}
}

//NOT SURE IF THIS IS DOING WHAT IS ASKED, DESCRIPTION ONLY STATED
//THAT IT RETURNS THE NUMERATOR OF THE DIFFERENCE
//HAD TO REMOVE CONST REFERENCE IN DECLARATION - KEPT GETTING ERRORS
int Fraction::Compare(const Fraction& f) //const
{
	Fraction result;
	result = *this - f;
	return result.numerator;
}

//OVERLOADED INPUT OPERATOR FOR RECEIVING SIMPLE FRACTIONS
istream& operator >>(istream& input, Fraction& frac)
{
	input >> frac.numerator;
	input.ignore();
	input >> frac.denominator;
	frac.Normalize();
	return input;
}

//OVERLOADED OUTPUT OPERATOR FOR RECEIVING SIMPLE FRACTIONS
ostream& operator <<(ostream& output, Fraction& frac)
{
	output << frac.numerator << "/" << frac.denominator;
	return output;
}
